package com.datasource.service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.datasource.SpringbootDatasourceBaomidouApplication;
import com.datasource.constants.DBConstants;
import com.datasource.entity.SysDeptEntity;
import com.datasource.entity.SysDictEntity;
import com.datasource.mapper.SysDeptMapper;
import com.datasource.mapper.SysDictMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import javax.annotation.Resource;

/**
 * @author ytj
 * @date 2021/12/14
 */
@Service
public class OrderService {
    @Resource
    private SysDictMapper sysDictMapper;
    @Resource
    private SysDeptMapper sysDeptMapper;

    private OrderService self(){
        return (OrderService) AopContext.currentProxy();
    }

    /**
     * 这边没有添加Transactional注解，因此不会开启事务，能够正常执行
     * */
    public void method1(){
        SysDeptEntity sysDeptEntity = sysDeptMapper.selectById("133438748537587302");
        System.out.println(sysDeptEntity);
        SysDictEntity sysDictEntity = sysDictMapper.selectById("10672468758000069");
        System.out.println(sysDictEntity);
    }

    /**
     * 这边因为添加Transactional注解因此会开启事务，spring的TransactionInterceptor会通过AOP进行拦截
     * 创建事务，创建事务肯定会获取数据源，会使用springDataSourceTransactionManager创建事务，通过threadLocal绑定在当前线程
     * 对于每个 DataSourceTransactionManager 数据库事务管理器，创建时都会传入其需要管理的 DataSource 数据源。
     * 在使用 dynamic-datasource-spring-boot-starter 时，它创建了一个 DynamicRoutingDataSource ，
     * 传入到 DataSourceTransactionManager 中 DynamicRoutingDataSource 负责管理我们配置的多个数据源
     * 本示例中就管理了 orders、users 两个数据源，并且默认使用 users 数据源。那么在当前场景下，
     * DynamicRoutingDataSource 需要基于 @DS 获得数据源名，从而获得对应的 DataSource ，
     * 结果因为我们在 Service 方法上，并没有添加 @DS 注解，所以它只好返回默认数据源，也就是 users，因此order数据源的数据会查询不到
     * */
    @Transactional
    public void method2(){
        SysDeptEntity sysDeptEntity = sysDeptMapper.selectById("133438748537587302");
        System.out.println(sysDeptEntity);
        SysDictEntity sysDictEntity = sysDictMapper.selectById("10672468758000069");
        System.out.println(sysDictEntity);
    }

    public void method3(){
        /**
         * 查询不到，因为默认的数据源是user
         * */
        self().method31();
        self().method32();
    }


    @Transactional
    public void method31(){
        SysDeptEntity sysDeptEntity = sysDeptMapper.selectById("133438748537587302");
        System.out.println(sysDeptEntity);
    }

    @Transactional
    public void method32(){
        SysDictEntity sysDictEntity = sysDictMapper.selectById("10672468758000069");
        System.out.println(sysDictEntity);
    }

    /**
     * 这边都能够查询到，是因为this不是代理对象，从而导致transaction注解不生效
     * */
    public void method33(){
        this.method31();
        this.method32();
    }


    /**
     * 执行正常
     * transaction开启事务之后在一个事务执行结束之后会和当前线程解绑，
     * 使用的都是方法上面DS指定的数据源，添加在mapper上的数据源失效
     * */
    public void method4(){
        self().method41();
        self().method42();
    }

    @Transactional
    @DS(DBConstants.DATASOURCE_ORDER)
    public void method41(){
        SysDeptEntity sysDeptEntity = sysDeptMapper.selectById("133438748537587302");
        System.out.println(sysDeptEntity);
    }

    @Transactional
    @DS(DBConstants.DATASOURCE_USER)
    public void method42(){
        SysDictEntity sysDictEntity = sysDictMapper.selectById("10672468758000069");
        System.out.println(sysDictEntity);
    }

    @Transactional
    @DS(DBConstants.DATASOURCE_ORDER)
    public void method5(){
        SysDeptEntity sysDeptEntity = sysDeptMapper.selectById("133438748537587302");
        System.out.println(sysDeptEntity);
        self().method51();
    }

    @Transactional(propagation= Propagation.REQUIRES_NEW)
    @DS(DBConstants.DATASOURCE_USER)
    public void method51(){
        SysDictEntity sysDictEntity = sysDictMapper.selectById("10672468758000069");
        System.out.println(sysDictEntity);
    }
}
